package com.fuelindustries.ant.tasks;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;

import com.fuelindustries.ant.FuelAntVariables;
import com.fuelindustries.ant.utils.AntUtils;
import com.fuelindustries.ant.utils.FileUtils;
import com.fuelindustries.ant.utils.OSUtils;

public class Fla extends Task 
{
	private String __file; //path to single fla file
	private String __build = "publish"; //the build action publish, test, export
	private String __swf; //the swf file. Only required when build is set to export.
	private boolean __close; //close the document after it's compiled
	private String __flashpath; // the path to the Flash Application
	private boolean __verbose = false;
	
	private String __jsflfile;
	private String __outputfile;
	private String __errorfile;
	
	public void execute() throws BuildException
	{
		boolean hasErrors = false;
		String message = "";
		
		try
		{
			checkForErrors();
			createJSFL();
			runJSFL();
		}
		catch( Exception e )
		{
			hasErrors = true;
			message = e.getMessage();
		}
		finally
		{
			cleanup();
		}
		
		if( hasErrors )
		{
			trace( " " );
			trace( message );
			throw new BuildException( "Fla Errors during " + __file );
		}	
	}
		
	private void checkForErrors() throws BuildException, IOException
	{
		File fla = new File( __file );
		if( !fla.exists() )
		{
			throw new IOException( "The Fla " + __file + " doesn't exist" );
		}
		
		trace( __build + " " + __file );
		
		if( __build.equals( FuelAntVariables.EXPORT ) )
		{
			if( __swf == null ) 
			{
				throw new BuildException( "The swf property has not been set" );
			}
			
			File swf = new File( __swf );
			if( !swf.exists() )
			{
				throw new IOException( "The SWF " + __swf + " doesn't exist" );
			}
		}

		if( __build.equals( FuelAntVariables.EXPORT ) || __build.equals( FuelAntVariables.PUBLISH ) || __build.equals( FuelAntVariables.TEST ) )
		{
			
		}
		else
		{
			throw new BuildException( "build variable not set to any of the valid values - publish, test, export" );
		}
		
	}
	
	public void createJSFL() throws IOException
	{			
		__errorfile = FuelAntVariables.BASE_DIR + FuelAntVariables.TEMP_DIR + "/" + FuelAntVariables.ERROR_FILE;
		__outputfile = FuelAntVariables.BASE_DIR + FuelAntVariables.TEMP_DIR + "/" + FuelAntVariables.OUTPUT_FILE;
		__jsflfile = FuelAntVariables.BASE_DIR + FuelAntVariables.TEMP_DIR + "/" + FuelAntVariables.FLA_JSFL;
		
		FileWriter writer = new FileWriter( __jsflfile );
		BufferedWriter buffer = new BufferedWriter( writer );
		
		buffer.write( "fl.compilerErrors.clear();" );
		buffer.newLine();
		
		buffer.write( "fl.outputPanel.clear()" );
		buffer.newLine();
				
		//buffer.write( "var doc = fl.openDocument( \"file:///" + __file + "\" );");
		
		buffer.write( "var doc = fl.openDocument( \"file:///" + __file.replace( "\\", "/") + "\" );");
		
		
		buffer.newLine();
		
		if( __build.equals( FuelAntVariables.TEST ) )
		{
			buffer.write( "doc.testMovie();" );
		}
		else if( __build.equals( FuelAntVariables.EXPORT ) )
		{
			buffer.write( "doc.exportSWF( \"file:///" + __swf + "\", true );");
		}
		else
		{
			buffer.write( "doc.publish();" );
		}
		
		buffer.newLine();

		buffer.write( "fl.compilerErrors.save( \"file:///" + __errorfile + "\", true, true );" );
		buffer.newLine();
		
		buffer.write( "fl.outputPanel.save( \"file:///" + __outputfile + "\", true, true );" );
		buffer.newLine();
		
		if( __close )
		{
			buffer.write( "doc.close(false);" );
			buffer.newLine();
		}
		
		buffer.close();
		
		
	}
	
	private void runJSFL() throws IOException, InterruptedException, BuildException
	{
		String[] command = new String[]{};
		
		if( OSUtils.isWindows() )
		{
			command = new String[]{ __flashpath, __jsflfile };
		}
		else
		{
			command = new String[]{ "osascript", "-e", "tell app \"" + __flashpath + "\" to open posix file \""+ __jsflfile +"\"" };
		}
	
		Process result = Runtime.getRuntime().exec( command );
        result.waitFor();
                
        File outputFile = new File( __outputfile );
        while( !outputFile.exists() )
        {
        	//sit in a loop until the output file exists
        }
        
        File errorFile = new File( __errorfile );
        while( !errorFile.exists() )
        {
        	//sit in a loop until the error file exists
        }

        InputStream inStream;
        String line;
        StringBuffer output = new StringBuffer();
        
        //get the results from the command
        if( result.exitValue() != 0 ) 
        {
        	inStream = result.getErrorStream();
        } 
        else 
        {
        	inStream = result.getInputStream();
        }
        
        BufferedReader out = new BufferedReader(new InputStreamReader(inStream));
        
        while( ( line = out.readLine() ) != null ) 
        {
           output.append(line + "\n");
        }
        
        //display any results if there are any
        String resultoutput = output.toString().trim();
        if( __verbose )
        {
	        if( resultoutput.length() > 0 )
	        {
	        	trace( "Command output " + resultoutput );
	        }
        }
        
        //read the error.txt file
        String errorstr = FileUtils.getContents(errorFile).trim();
        boolean hasErrors = false;
        
        //read the output.txt file
        String outputstr = FileUtils.getContents(outputFile).trim();
        
        //display the output.txt file
        if( __verbose )
        {
	        if( outputstr.length() > 0 )
	        {
	        	trace( outputstr );
	        }
        }
        
        //the error.txt file isn't blank then there are errors
        if( errorstr.length() > 0 )
        {
        	
        	if( !errorstr.equals("0 Error(s), 0 Warning(s)"))
        	{
        		hasErrors = true;
        	}
        	
        	//trace( errorstr );
        }
        
        if( hasErrors )
        {
        	throw new BuildException(errorstr);
        }
	}
	
	
	
	private void cleanup()
	{
		File e = new File( __errorfile );
		while( e.exists() )
		{
			e.delete();
		}
		
		File o = new File( __outputfile );
		while( o.exists() )
		{
			o.delete();
		}
		
		File j = new File( __jsflfile );
		while( j.exists() )
		{
			j.delete();
		}
	}
	
	public void setFlashPath( String path )
	{
		__flashpath = path;
	}
	
	public void setClose( boolean close )
	{
		__close = close;
	}
	
	public void setFile( String file )
	{
		__file = file;
	}
	
	public String getFile()
	{
		return( __file );
	}
	
	public void setBuild( String build )
	{
		__build = build;
	}
	
	public void setSwf( String swf )
	{
		__swf = swf;
	}
	
	public void trace( String msg )
	{
		System.out.println( msg );
	}
	
	public void setVerbose( Boolean val )
	{
		__verbose = val;
	}
}
